<?php

/**
 * Date: 18 November 2008
 * Author: Anthony Gallon
 * Handles the sale and granting of subscriptions to members of IUsers
 *
 * Has hooks to API methods on modules of CMSms:
 *
 * $module->ISubscribe_AddSubscriptionAction($ISubscribe, $subscriptionData, $priceData, $gatewayObject, $expireTstamp)
 * 	- Defined in ISubscribe::AddSubscription();
 * 	- Called whenever a subscription is granted, usually after successful payment
 *
 */



if(!class_exists('Antz')){
    return;
}else if(!class_exists('IUsers')){
    return;
}


class ISubscribe extends CMSModule
{
protected $ISubscribe_Config = array();
protected $validAttributes = array(
    'text' => 'Text (255)',
    'longtext' => 'Long text (5000)',
    'image' => 'Image (jpg, gif, png)',
    'flash' => 'Flash movie',
    'file' => 'File download'
);


public function IUsers_ProfileFormFields($params){

	$params[] = array(
		'name' => 'test',
		'value' => 'test value',
		'type' => 'text',
		'label' => 'Test label'
	);
	return $params;
}

public function __construct(){
    parent::CMSModule();

    $this->dirname = str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__));

    if(!class_exists('Antz') || !($Antz = Antz::registry('Antz')) || !is_object($Antz) || !($Antz instanceof Antz)) {
        //throw new Exception('Tried to instantiate module: '.$this->GetName().', but required module "Antz" is not available.');
        return;
    };

	require_once('classes/ISubscribe_Payment_Gateway.php');

    // automatically load our configuration settings once only
    if(count($this->ISubscribe_Config) == 0) $this->LoadConfig();
    if(count($this->ISubscribe_Config) == 0){
        // probably not installed, can't proceed
        return;
    };

	$DB = Antz::registry('db');

	$gateways = $DB->fetchAll("SELECT * FROM {$this->config['db_prefix']}isubscribe_payment_gateways");
	foreach($gateways as $k=>$v){
		require_once('gateways/'.$v['class_name'].'.php');
	};

}


public function IUsers_AdminSearchDisplay($params, $output){
  $DB = Antz::registry('db');
  $tables = $params['tables'];
  foreach($tables as $tableKey => $table){
    $uData = $table['user_data'];
    $subscriptions = $DB->fetchAll("SELECT * FROM {$this->config['db_prefix']}isubscribe_users_to_subscriptions WHERE user_id = '{$uData['id']}' ORDER BY expire_tstamp");
    foreach($table['rows'] as $rowKey => $row){
      if($row['name'] == 'groups'){
        if(count($subscriptions)==0) $subs = $this->Lang('not_a_subscriber');
        else{
          $subs = '';
          foreach($subscriptions as $k=>$v){
            $subs .= '<h4>'.date('d M Y', $v['expire_tstamp']).'</h4> 
            <p><strong>'.$DB->oneValue(cms_db_prefix().'isubscribe_subscriptions', 'title', "id = '{$v['subscription_id']}'").'</strong></p>';
          };
        };
        $newData = array(
          'th' => $this->Lang('subscriptions'),
          'td' => $subs,
          'name' => 'subscriptions'
        );
        $tables[$tableKey]['rows'] = array_insert($tables[$tableKey]['rows'], $rowKey+1, $newData);
        $rowKey++;
      }
    }
  }
  return array('tables'=>$tables);
}


public function IUsers_AdminSearchForm($params){
  $DB = Antz::registry('db');
  $formFields = $params['form_fields'];
  $sParams = $params['search_params'];
  if(!isset($sParams['subscription'])) $sParams['subscription'] = '0';
  $subs = $DB->fetchAll("SELECT * FROM {$this->config['db_prefix']}isubscribe_subscriptions ORDER BY is_deleted ASC, is_active DESC, title ASC");
  $subOpts = array('0'=>$this->Lang('any_subscriptions'));
  foreach($subs as $k=>$v){
    $subOpts[$v['id']] = $v['title'].' ['.$v['keyname'].']';
  };
  $formFields[] = array(
    'type' => 'select',
    'name' => 'subscription',
    'value' => post('subscription', $sParams['subscription']),
    'label' => $this->Lang('subscriptions'),
    'options' => $subOpts
  );

  return array('form_fields' => $formFields, 'search_params' => $sParams);
}



public function IUsers_AdminSearchProcess($params){
  $sel = $params['select_object'];
  $sParams = $params['search_params'];
  
  // $sParams['subscription'] must be set
  if(!isset($sParams['subscription'])) $sParams['subscription'] = '0';
  
  // update the search params if the form has been submitted
  if(post('subscription', NULL) !== NULL){
    $subid = (int) post('subscription');
    $sParams['subscription'] = $subid;
  }
  
  // add the where clause if filtering
  if($sParams['subscription'] != '0'){
    $sel->join(cms_db_prefix().'isubscribe_users_to_subscriptions isubs', 'iusers.id = isubs.user_id');
    $sel->where('isubs.subscription_id', $sParams['subscription']);
  };
  
  // return the params
  $params = array(
    'select_object' => $sel,
    'search_params' => $sParams
  );

  return $params;
}



/**
 * Adds a user to the designated groups, creates the expiration time,
 * executes any php code configured by the subscription, and calls
 * the method ISubscribe_AddSubscriptionAction for each module in which
 * that method exists.
 * Accepts:
 * $priceData - row from cms_isubscribe_subscription_prices
 * $subData - row from cms_isubscribe_subscriptions
 * $gwObj - an instance of the gateway that the user has used to pay by
 * $userid - id in cms_iusers, derived from $USER->userid if not provided
 * Returns: new expiration tstamp
 */
public function AddSubscription($priceData, $subData, $gwObj, $userid=''){
	$DB = Antz::registry('db');
	$USER = Antz::registry('user');
	$CRYPT = Antz::registry('crypt');
	global $gCms;

	$secsDuration = ($subData['duration']*86400);

	if($userid == '') $userid = (int) $USER->userid;
	$userid = (int) $userid;

	if($userid == 0) return false;

	// load our user data
	$uData = $DB->fetchRow("SELECT * FROM {$this->config['db_prefix']}iusers WHERE id = '{$userid}'");

	$groups = explode(',', $subData['groups']);

	// find if they have an existing subscription, get the greater expiration date to add our new value to
	if($subData['duration'] > 0){
		$currentExpiration = time();
		if($this->GetConfig('cumulative_subscriptions')){
			foreach($groups as $groupKey){
				if(($expData = $DB->fetchRow("SELECT * FROM {$this->config['db_prefix']}isubscribe_expirations WHERE user_id = '{$userid}' AND group_key = '{$groupKey}'"))){
					if($this->GetConfig('greater_cumulative_subscriptions')){
						if($expData['expire_tstamp'] > $currentExpiration) $currentExpiration = $expData['expire_tstamp'];
					}else{
						if($expData['expire_tstamp'] < $currentExpiration) $currentExpiration = $expData['expire_tstamp'];
					};
				};
			};
		};
		$expirationTstamp = $currentExpiration+$secsDuration;
	}else{
		// never expires
		$expirationTstamp = 0;
	};

	$groups = explode(',', $subData['groups']);

	foreach($groups as $groupKey){
		$groupKey = preg_replace('/[^a-zA-Z0-9\-_]/', '', $groupKey);

		if($DB->countRows(cms_db_prefix().'iusers', "id = '{$userid}'")==0){
			continue;
		};

		if($DB->countRows(cms_db_prefix().'iusers_groups', "keyname = '{$groupKey}'")==0){
			continue;
		};

		$dbParams = array(
			'user_id' => $userid,
			'group_key' => $groupKey
		);

		$DB->insert(cms_db_prefix().'iusers_to_groups', $dbParams);

		$dbParams['expire_tstamp'] = $expirationTstamp;
		$dbParams['has_expired'] = 0;
		$dbParams['price_obj'] = serialize($priceData);
		$dbParams['subscription_obj'] = serialize($subData);
		$dbParams['gateway_obj'] = $CRYPT->crypt(serialize($gwObj));

		$DB->insert(cms_db_prefix().'isubscribe_expirations', $dbParams);


//		var_dump($dbParams);

	};

	// add the subscription to userid association
	$dbParams = array(
		'user_id' => $userid,
		'subscription_id' => $subData['id'],
		'expire_tstamp' => $expirationTstamp
	);

	$DB->insert(cms_db_prefix().'isubscribe_users_to_subscriptions', $dbParams);

	// call the user defined function, if exists
	if(trim($subData['php_code'])!='') {
		exec($subData['php_code']);
	};

	// call any other modules that may have an API for this action
	$hookParams = array(
    'isubscribe_object' => $this,
    'subscription_data' => $subData,
    'price_data' => $priceData,
    'gateway_object' => $gwObj,
    'expire_tstamp' => $expirationTstamp,
    'user_data' => $uData
  );
  
	$newParams = Antz::Hookup('ISubscribe_AddSubscription', $hookParams);
  unset($newParams);

	return $expirationTstamp;
}

function HasAdmin(){return true;}
function GetAdminSection() {return 'usersgroups';}
function VisibleToAdminUser() {
    $vis = false;
    if($this->CheckPermission($this->GetName().' Manage')) $vis = true;
    if($this->CheckPermission($this->GetName().' Config')) $vis = true;
    if($this->CheckPermission($this->GetName().' View')) $vis = true;
    return $vis;
}
function GetName(){return 'ISubscribe';}
function GetFriendlyName(){return $this->Lang('friendlyname');}
function GetVersion(){return '0.1.1';}
function IsPluginModule(){return true;}
function GetDependencies(){return array('Antz'=>'1.0.0', 'IUsers'=>'0.9.0');}
function GetHelp(){return file_get_contents($this->config['root_path'].'/modules/'.$this->GetName().'/docs/help.html');}
function GetChangeLog(){return nl2br(file_get_contents($this->config['root_path'].'/modules/'.$this->GetName().'/docs/changelog-0.0.1.txt'));}


function Upgrade($fromVersion, $toVersion){
    global $gCms;
    if(!class_exists('Antz', false)) return;
    $DB = Antz::registry('db');
    switch(version_compare($fromVersion, '0.1.0')){
      case -1:
        // too old for upgrade
        return;
      break;
      case 0:
        if(version_compare($fromVersion, $toVersion)==-1){
          // add a column to the table for ipn data
          $q = "ALTER TABLE {$gCms->config['db_prefix']}isubscribe_offsite_payments ADD ipn_data TEXT AFTER ipn_received";
          $DB->query($q);
        }
      break;
      case 1:
        // future upgrades here
        
      break;
      
    }

    if($fromVersion == '0.1.0'){
        $this->CreatePermission($this->GetName().' Users', $this->Lang('perm_manage_users'));
    }

}



function Install(){
        include('install/install.php');
}
function UnInstall(){
        include('install/uninstall.php');
}

function InstallPostMessage()
{
    $DB = Antz::registry('db');
    return 'Installation success. First thing you should do is activate and configure your payment gateways.';

}
function UninstallPreMessage(){
        return 'This will delete all expiration dates. User to group associations will not be altered.';
}
function UninstallPostMessage(){
    return $this->GetName().' was successfully uninstalled';
}

function MergeLang($thelang){
    // get our language as array
    global $gCms;

    if($this->curlang!='') $ourlang = $this->curlang;
    else if(isset($gCms->current_language)) $ourlang = $gCms->current_language;
	else $ourlang = $this->DefaultLanguage();
	//	else $ourlang = $USER->getLang();
	$lang = array();
	if(file_exists($this->dirname.'/lang/ext/'.$ourlang.'.php')) include($this->dirname.'/lang/ext/'.$ourlang.'.php');
	else include($this->dirname.'/lang/en_US.php');
	return array_merge($thelang, $lang);
}

function DoAction($action, $id, $params, $returnid=-1){
	$DB = Antz::registry('db');

	// get hold of our objects
	$SMARTY = $this->smarty;
	$USER = Antz::registry('user');
	$CRYPT = Antz::registry('crypt');
	$Antz = Antz::registry('Antz');
	$IUsers = $this->GetModuleInstance('IUsers');
	global $gCms;
	$rootPath = str_replace(DIRECTORY_SEPARATOR, '/', $gCms->config['root_path']);
        $dirname = $this->dirname;

	// load our language array and give it to smarty
	$ourlang = array();
	$ourlang = $this->MergeLang($ourlang);
	$this->smarty->assign('lang', $ourlang);

	// dispatch our action
	switch ($action){
		case 'default':
			Antz::redir($Antz->getUrlById($this->GetConfig('advertisement_id')));
		break;
		case 'make-link':
			if(!isset($params['subscription'])) return;
			$params['subscription'] = preg_replace('/[^a-zA-Z0-9_\-]/', '', $params['subscription']);
			$subData = $DB->fetchRow("SELECT * FROM {$this->config['db_prefix']}isubscribe_subscriptions WHERE keyname = '{$params['subscription']}'");
			if(!is_array($subData) || count($subData)==0) return;
			// we have a valid subscription
			if(!isset($params['content']) || trim($params['content'])=='') $params['content'] = $subData['title'];
			$url = $Antz->getUrlById($this->getConfig('purchase_subscription_id'));
			$url = $Antz->addParamsToUrl($url, array('subscription'=>$params['subscription']));
			$link = '<a href="'.$url.'" class="'.$params['class'].'" id="'.$params['id'].'">'.$params['content'].'</a>';
			echo $link;
			return;
		break;
		case 'cron':
		  include('actions/cron.php');
		break;
		case 'purchase-subscription':
			include('actions/purchase-subscription.php');
		break;
		case 'defaultadmin':

			// prepare for tinymce textareas
			if(!isset($_SESSION['tiny_live_textareas'])) $_SESSION['tiny_live_textareas'] = '';

			echo '<script type="text/javascript" src="'.$this->config['root_url'].'/modules/TinyMCE/tinymce/jscripts/tiny_mce/tiny_mce.js"></script>';
			echo '<script type="text/javascript" src="'.$this->config['root_url'].'/modules/TinyMCE/tinyconfig.php"></script>';
			echo '<link href="'.$this->config['root_url'].'/modules/Antz/css/forms.css" rel="stylesheet" />';
			echo '<link href="'.$this->config['root_url'].'/modules/'.$this->GetName().'/css/backend.css" rel="stylesheet" />';
                        echo '<script src="'.$this->config['root_url'].'/modules/Antz/js/AntzBase.js" type="text/javascript"></script>';
			echo '<script src="'.$this->config['root_url'].'/modules/'.$this->GetName().'/js/ISubscribe_Admin.js" type="text/javascript"></script>';
			echo '<script src="'.$this->config['root_url'].'/lib/scriptaculous/effects.js" type="text/javascript"></script>';
			echo '<script src="'.$this->config['root_url'].'/lib/scriptaculous/util.js" type="text/javascript"></script>';


			$tabs = array();
            if($this->CheckPermission($this->GetName().' Manage')){
            	$tabs['new'] = $this->Lang('new_subscription');
            	$tabs['edit'] = $this->Lang('subscriptions');
            	$tabs['new_notification'] = $this->Lang('new_notification');
            	$tabs['edit_notification'] = $this->Lang('notifications');
            };
            if($this->CheckPermission($this->GetName().' Config')){
            	$tabs['install_gateway'] = $this->Lang('install_gateway');
            	$tabs['config_gateway'] = $this->Lang('gateways');
            	$tabs['currencies'] = $this->Lang('currencies');
            	$tabs['config'] = 'Config';
            };
            if($this->CheckPermission($this->GetName().' Users')){
                $tabs['users'] = $this->Lang('users');
            }

            
            if(count($tabs)==0) {
                echo '<p>'.$this->Lang('insufficient_permissions').'</p>';
                return;
            };

			      $actionUrls = array();

            if(!empty($params['active_tab'])) $selectedTab = $params['active_tab'];
            else $selectedTab = 'edit';

            if(!array_key_exists($selectedTab, $tabs)){
            	echo '<p>'.$this->Lang('insufficient_permissions').'</p>';
                return;
            };

			// calculate the urls to get to each tab
        	foreach($tabs as $tab=>$title){
            	$params['active_tab'] = $tab;
            	$actionUrls[$tab] = $this->GetAdminUrl($params, $id, $this->GetName(), 'defaultadmin');
        	};
        	$this->smarty->assign('actionUrls', $actionUrls);
			$this->smarty->assign('tabs', $tabs);

            /**
             *  displaying our tabs
             */                         

            // some tabs are hidden and disguised under another tab
            $hiddenTabs = array(
                'edit' => 'new',
                'edit_notification' => 'new_notification',
                'config_gateway' => 'install_gateway',
                '' => 'users'
            );

			$adminTabs = array();
	        foreach($tabs as $k=>$title){
	            if($k==$selectedTab 
                || (isset($hiddenTabs[$k]) && $hiddenTabs[$k] == $selectedTab)) 
                    $class = 'selected';
	            else $class = '';
	            if(in_array($k, $hiddenTabs)) $class .= ' hidden';
	            $adminTabs[] = array(
	                'key'=>$k,
	                'title' => $title,
	                'url' => $actionUrls[$k],
	                'class' => $class,
	            );
	        };
	        $this->smarty->assign('adminTabs', $adminTabs);

			echo $this->processTemplate('admin.tabs.php');

            echo '<div id="admin-content">';
			include('actions/admin.'.$selectedTab.'.php');
            echo '</div>';

        	// time to add our error messages
        	$errorMsg = str_replace(array("\n", "\r"), '', Antz::getError());

	        if($errorMsg != '')
    	      echo '<script type="text/javascript" language="javascript">showErrorMsg(\''.$errorMsg.'\', \''.$this->config['root_url'].'\')</script>';
        	$successMsg = str_replace(array("\n", "\r"), '', Antz::getSuccess());

	        if($successMsg != '')
    	      echo '<script type="text/javascript" language="javascript">showSuccessMsg(\''.$successMsg.'\', \''.$this->config['root_url'].'\')</script>';



		break;
	};//end swtich action






}// end DoAction


function GetAdminUrl($params, $id, $name, $action, $inline=true){
    $Antz = Antz::registry('Antz');
    return $Antz->getUrl($params, $id, $name, $action, $inline);
}

function LoadConfig(){
    $DB = Antz::registry('db');
    global $gCms;
    // make sure we have been installed!
    if(!($config = $DB->fetchAll("SELECT * FROM {$this->config['db_prefix']}isubscribe_config"))) return;
    foreach($config as $k=>$v){
        $this->ISubscribe_Config[$v['k']] = $v['v'];
    };
}


function GetConfig($k){
    if(isset($this->ISubscribe_Config[$k])) return $this->ISubscribe_Config[$k];
    else if($this->ThrowConfigExceptions) throw new Exception($this->GetName().'->GetConfig was asked to find a non-existing key: '.$k);
    else return false;
}


function TransferCartItems(){
	$USER = Antz::registry('user');
	$DB = Antz::registry('db');
	$cart = $USER->ISubscribe_Cart;
	$items = $cart->getItemsAsArray();
	foreach($items as $k=>$item){

		if($item['obj']->GetExpireTstamp()==0) $expireTstamp = 0;
		else $expireTstamp = (time() + $item['obj']->GetExpireTstamp());

		$dbParams = array(
			'user_id' => $USER->userid,
			'event' => $item['id'],
			'expire_tstamp' => $expireTstamp,
			'qty' => $item['qty']
		);

		$DB->insert(cms_db_prefix().'isubscribe_purchases', $dbParams);
		$cart->removeItem($item['id']);
	}
}

function GetGatewayInstance($name){
	if(file_exists($this->dirname.'/gateways/'.$name.'.php')){
		include_once($this->dirname.'/gateways/'.$name.'.php');
		if(!class_exists('ISubscribe_Gateway_'.$name)) return NULL;
		$name = 'ISubscribe_Gateway_'.$name;
		$obj = new $name;
		return $obj;
	}
	return NULL;
}


}// end class
